package demo.topic12.singleton;

import java.io.Serializable;

/**
 * 单例模式优化（完整）
 * 1. 使用同步保证线程安全
 * 2. 使用 volatile 关键字：volatile 提醒编译器它后面定义的变量随时都有可能改变，因此编译后的程序每次需要存储或读取这个变量的时候，
 * 都会直接从变量地址中读取数据。如果没有volatile关键字，则编译器可能优化读取和存储，可能暂时使用寄存器中的值，如果这个变量由别的程序
 * 更新了的话，将出现不一致的现象。
 * 3. 防止反射调用私有构造方法。
 * 4. 让单例类序列化安全 Serializable。
 */
public class Singleton implements Serializable {  // 4. Serializable，让单例类序列化安全
    // 2. volatile 修饰，保证变量的一致性
    private volatile static Singleton singleton = null;

    private Singleton() {
        // 3. 抛异常，防止反射调用私有构造方法
        if (singleton != null) {
            throw new RuntimeException("此类对象是单例模式，已经被实例化");
        }
    }

    public static Singleton getSingleton() {

        if(singleton == null) {
            // 1. 同步锁，保证线程安全
            synchronized (Singleton.class) {
                if(singleton == null) {
                    singleton = new Singleton();
                }
            }
        }

        return singleton;
    }
}
